package com.ckjava.test.service.base;

import com.ckjava.test.domain.base.BaseJpaEntity;
import com.ckjava.xutils.Constants;
import com.ckjava.xutils.http.Page;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.*;

@Transactional(readOnly = true)
public abstract class BaseJpaCrudService<E extends BaseJpaEntity> implements Constants {

    @PersistenceContext
    private EntityManager entityManager;

    public abstract Class<E> getClassType();

    /**
     * 根据 id 查询一个对象
     * @param id
     * @return
     */
    public E get(Long id) {
        return entityManager.find(getClassType(), id);
    }

    /**
     * 获取所有
     * @return
     */
    public List<E> findAll() {
        List<E> dataList = new ArrayList<>();
        try {
            dataList = entityManager.createQuery( "from " + getClassType().getName(), getClassType()).getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return dataList;
    }

    /**
     * 分页获取数据
     * @param e
     * @return
     */
    public Page<E> getPage(E e) {
        StringBuilder qlString = new StringBuilder();
        qlString.append("from " + getClassType().getName());
        qlString.append(" where 1=1 ");

        Map<String, String> conditionMap = e.getConditionMap();
        for (Iterator<Map.Entry<String, String>> it = conditionMap.entrySet().iterator(); it.hasNext();) {
            Map.Entry<String, String> entry = it.next();
            // key name, value like,张三
            // key age, value =,10

            String key = entry.getKey();
            String value = entry.getValue();
            String op = value.split(SPLITER.COMMA)[0];
            qlString.append(" and " + key + " " + op + " :" + key); // name LIKE :name 或者 age = :age
        }

        qlString.append("limit :start,:pageSize");
        qlString.append("order by :desc");

        TypedQuery<E> typedQuery = entityManager.createQuery(qlString.toString(), getClassType())
                .setParameter("start", e.getStart())
                .setParameter("pageSize", e.getPageSize())
                .setParameter("desc", e.getDesc());

        for (Iterator<Map.Entry<String, String>> it = conditionMap.entrySet().iterator(); it.hasNext();) {
            Map.Entry<String, String> entry = it.next();
            String key = entry.getKey();
            String value = entry.getValue();
            String valued = value.split(SPLITER.COMMA)[1];
            typedQuery.setParameter(key, valued);
        }

        return new Page<>(e.getStart(), e.getPageSize(), typedQuery.getMaxResults(), typedQuery.getResultList());
    }

    @Transactional
    public void saveOrUpdate(E e) {
        if (e.getId() == null) {
            save(e);
        } else {
            update(e);
        }
    }

    @Transactional
    public void save(E e) {
        e.setDelFlag(E.DEL_NO);
        e.setCreateDate(new Date());
        entityManager.persist(e);
    }

    @Transactional
    public E update(E e) {
        e.setUpdateDate(new Date());
        return entityManager.merge(e);
    }

    @Transactional
    public void delete(E e) {
        e.setDelFlag(E.DEL_YES);
        update(e);
    }

    @Transactional
    public void delete(Long id) {
        E e = get(id);
        delete(e);
    }

}
